package toubiao.test;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import toubiao.test.bean.Student;
import toubiao.test.bean.Teacher;


public class Temp {

	private static Logger logger=LoggerFactory.getLogger(Temp.class);

	/**
	 * 为对象 中 相应 属性 设置为null,其中 在对象属性中的 ：T;T[];Collection<T>都可关联进行处理.
	 * @param clazz 预处理 类型 T
	 * @param t  预处理的对象，可以为 对象 T、数组 T[] 或集合 Collection<T>
	 * @param fieldNameSet 设置为Null的属性名称
	 * @return 处理后的对象
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static <T> T setObjectFieldNull(Class<T> clazz,T t,Set<String> fieldNameSet) throws IllegalArgumentException, IllegalAccessException{
		if(t==null){
			return null;
		}
		if(fieldNameSet==null || fieldNameSet.size()==0){
			return t;
		}
		Field[] fields=t.getClass().getDeclaredFields();
		for(Field field:fields){
			field.setAccessible(true);
			String fieldName=field.getName();
			Object fieldValue=field.get(t);
			Class fieldClass=field.getType();
			
			//如果 fieldValue为空 或者 fieldNameSet包含 fieldName，设置为空后，遍历下一属性
			if(fieldValue==null) continue;
			if(fieldNameSet.contains(fieldName)){
				field.set(t, null);
				continue;
			}
			
			//fieldValue为以下3种情况需要递归:1.T[] ; 2,Collection<T>   3.T
			//1.
			if(fieldClass.isArray()){
				Object[] objects=(Object[]) fieldValue;
				logger.debug(field.getName() + " = " +fieldValue);
				for(Object object:objects){
					if(object.getClass()==clazz){
						setObjectFieldNull(clazz,(T)object,fieldNameSet);
					}else{
						break;
					}
				}
			} 
			//2.
			if(fieldValue instanceof Collection){
				logger.debug(field.getName() + " = " +fieldValue);
				for(Object object:(Collection)fieldValue){
					if(object.getClass()==clazz){
						setObjectFieldNull(clazz,(T)object,fieldNameSet);
					}else {
						break;
					}
					
				}
			}
			//3.
			if(fieldClass==clazz){
				logger.debug(field.getName() + " = " +fieldValue);
				setObjectFieldNull(clazz,(T)fieldValue,fieldNameSet);
			}
		}
		return t;
	}
	
	/**
	 * 为对象 中  在排除列表为的 属性 设置为null,其中 在对象属性中的 ：T;T[];Collection<T>都可关联进行处理.
	 * @param clazz 预处理 类型 T
	 * @param t  预处理的对象，可以为 对象 T、数组 T[] 或集合 Collection<T>
	 * @param fieldNameSet 保留原属性的名称
	 * @return 处理后的对象
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static <T> T setObjectFieldNullExcept(Class<T> clazz,T t,Set<String> fieldNameKeepSet) 
			throws IllegalArgumentException, IllegalAccessException{
		if(t==null){
			return null;
		}
		if(fieldNameKeepSet==null || fieldNameKeepSet.size()==0){
			return null;
		}
		Set<String> fieldNameSet=new HashSet<>();
		Field[] fields=t.getClass().getDeclaredFields();
		for(Field field:fields){
			fieldNameSet.add(field.getName());
		}
		fieldNameSet.removeAll(fieldNameKeepSet);
		return setObjectFieldNull(clazz,t,fieldNameSet);
	}
	
	//重载 setObjectFieldNull
	public static <T> T setObjectFieldNull(Class<T> clazz,T t,String... fieldNames) throws IllegalArgumentException, IllegalAccessException{
		Set<String> fieldNameSet=new HashSet<>();
		if(fieldNames!=null){
			for(String fieldName:fieldNames ){
				fieldNameSet.add(fieldName);
			}
		}
		return setObjectFieldNull(clazz, t, fieldNameSet);
	}
	
	
	//重载 setObjectFieldNullExcept
	public static <T> T setObjectFieldNullExcept(Class<T> clazz,T t,String... fieldNames) 
			throws IllegalArgumentException, IllegalAccessException{
		Set<String> fieldNameSet=new HashSet<>();
		if(fieldNames!=null){
			for(String fieldName:fieldNames ){
				fieldNameSet.add(fieldName);
			}
		}
		return setObjectFieldNullExcept(clazz, t, fieldNameSet);
	}
	
	
	
	@Test
	public void testDemo1() throws IllegalArgumentException, IllegalAccessException{
		Teacher teacher1=new Teacher("t1", 1);
		Teacher teacher2=new Teacher("t2", 2);
		Teacher teacher3=new Teacher("t3", 3);
		
		teacher1.setTeacherArray(new Teacher[]{teacher2,teacher3});
		teacher1.getTeacherSet().add(teacher2);
		teacher1.getTeacherSet().add(teacher3);
		
		Student student1=new Student("s1", 101);
		Student student2=new Student("s2", 102);
		teacher2.getStudentSet().add(student1);
		teacher2.getStudentSet().add(student2);
		teacher1.setStudentArray(new Student[]{student1,student2});
		teacher1.getStudentSet().add(student1);
		teacher1.getStudentSet().add(student2);
		//Object[] objects=teacher1.getStudentArray();
		Set<String> set=new HashSet<String>();
		//set.add("teacherArray");
		//set.add("teacherSet");
		//studentSet
		set.add("studentSet");
		set.add("studentArray");
		student1.getTeacherSet().add(teacher1);
		setObjectFieldNull(Teacher.class,teacher1,set);
		logger.debug(teacher1.toString());
		logger.debug("**************************");
		
		set.clear();
		set.add("teacherName");
		
		set.add("teacherId");
		set.add("teacherSet");
		set.add("teacherArray");
		
		setObjectFieldNullExcept(Teacher.class,teacher1,set);
	}
	
	
	
	public boolean isArrayOrCollection(Object object){
		if(object==null){
			return false;
		}
		if(object.getClass().isArray()){
			return true;
		}
		if(object instanceof Collection){
			return true;
		}
		return false;
	}
}
